package ldh.fx.adminfx;

import com.jfoenix.controls.JFXButton;
import eu.hansolo.medusa.Gauge;
import eu.hansolo.medusa.GaugeBuilder;
import eu.hansolo.medusa.tools.GradientLookup;
import javafx.application.Application;
import javafx.beans.InvalidationListener;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.geometry.Side;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.chart.*;
import javafx.scene.control.*;
import javafx.scene.control.cell.CheckBoxTableCell;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.paint.Stop;
import javafx.scene.text.Text;
import javafx.scene.text.TextFlow;
import javafx.stage.Screen;
import javafx.stage.Stage;
import ldh.fx.adminfx.cell.ObjectListCell;
import ldh.fx.adminfx.commpont.LPane;
import ldh.fx.adminfx.commpont.LText;
import ldh.fx.adminfx.commpont.grid.NoHeaderTableView;
import ldh.fx.adminfx.pojo.Activity;
import ldh.fx.adminfx.pojo.User;
import ldh.fx.adminfx.util.RegionUtil;
import org.kordamp.ikonli.fontawesome.FontAwesome;
import org.kordamp.ikonli.javafx.FontIcon;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.function.Supplier;

public class SampleDemo extends Application {

    private VBox leftPane = new VBox();
    private StackPane contentPane = new StackPane();

    @Override
    public void start(Stage primaryStage) throws Exception {
        leftPane.getStyleClass().add("demo-left-pane");
        contentPane.getStyleClass().add("demo-content-pane");

        BorderPane borderPane = new BorderPane();
        borderPane.setTop(buildTop());
        ScrollPane leftContainer = new ScrollPane(leftPane);
        leftContainer.setFitToHeight(true);
        leftContainer.setFitToWidth(true);
        borderPane.setLeft(leftContainer);

        ScrollPane contentContainer = new ScrollPane(contentPane);
        contentContainer.setFitToHeight(true);
        contentContainer.setFitToWidth(true);
        borderPane.setCenter(contentContainer);

        buildTests();

        Scene scene = new Scene(borderPane, 800, 600);
//        scene.getStylesheets().add(this.getClass().getResource("/css/init.css").toExternalForm());
        scene.getStylesheets().add(this.getClass().getResource("/css/skin/blue.css").toExternalForm());
        scene.getStylesheets().add(this.getClass().getResource("/css/demo.css").toExternalForm());
        scene.getStylesheets().add(this.getClass().getResource("/css/bootstrapfx.css").toExternalForm());
        scene.getStylesheets().add(this.getClass().getResource("/css/component/lpane.css").toExternalForm());
        scene.getStylesheets().add(this.getClass().getResource("/css/chart.css").toExternalForm());
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private void buildTests() {
        addTest("LPane Demo", ()->{
            LPane lPane = new LPane("测试LPane");
            lPane.getTopLeftChildren().add(new JFXButton("demo"));
            lPane.getContentChildren().add(new Label("demo!!!!!!!!!!!!!!!!!"));
            lPane.getBottomRightChildren().add(new JFXButton("cloe"));
            return lPane;
        });

        addTest("LPane List demo", ()->{
            VBox vBox = new VBox(20);
            LPane lPane = new LPane("测试LPane");
            lPane.getTopLeftChildren().add(new JFXButton("demo"));
            lPane.getContentChildren().add(new Label("demo!!!!!!!!!!!!!!!!!"));
            lPane.getBottomRightChildren().add(new JFXButton("cloe"));
            lPane.setPrefHeight(200);

            LPane lPane2 = new LPane("测试LPane");
            lPane2.getTopLeftChildren().add(new JFXButton("demo"));
            lPane2.getContentChildren().add(new NoHeaderTableView<>());
            lPane2.getBottomRightChildren().add(new JFXButton("cloe"));
            lPane2.setPrefHeight(200);

            vBox.getChildren().addAll(lPane, lPane2);
            return vBox;
        });

        addTest("No header TableView", ()->{
            NoHeaderTableView<User> tableView = new NoHeaderTableView();

            TableColumn<User, Integer> tc1 = new TableColumn();
            tc1.setCellValueFactory(new PropertyValueFactory("id"));

            TableColumn<User, Integer> tc2 = new TableColumn();
            tc2.setCellValueFactory(new PropertyValueFactory("name"));

            TableColumn<User, Integer> tc3 = new TableColumn();
            tc3.setCellValueFactory(new PropertyValueFactory("age"));

            tableView.getColumns().addAll(tc1, tc2, tc3);

            List<User> userList = new ArrayList();
            for(int i=0; i<10; i++) {
                User user = new User();
                user.setId((long)Math.round(100));
                user.setName("test " + i);
                user.setAge((int)(Math.random() * 100));
                userList.add(user);
            }
            tableView.getItems().addAll(userList);
            return tableView;
        });

        addTest("TableView For Checkbox", ()->{
            TableView<User> tableView = new TableView();
            TableColumn<User, Boolean> tc0 = new TableColumn();
            tc0.setCellFactory(CheckBoxTableCell.forTableColumn(tc0));
            tc0.setGraphic(new CheckBox());

            TableColumn<User, Integer> tc1 = new TableColumn("id");
            tc1.setCellValueFactory(new PropertyValueFactory("id"));

            TableColumn<User, Integer> tc2 = new TableColumn("name");
            tc2.setCellValueFactory(new PropertyValueFactory("name"));

            TableColumn<User, Integer> tc3 = new TableColumn("age");
            tc3.setCellValueFactory(new PropertyValueFactory("age"));


            tableView.getColumns().addAll(tc0, tc1, tc2, tc3);

            List<User> userList = new ArrayList();
            for(int i=0; i<10; i++) {
                User user = new User();
                user.setId((long)Math.round(100));
                user.setName("test " + i);
                user.setAge((int)(Math.random() * 100));
                userList.add(user);
            }
            tableView.getItems().addAll(userList);
            return tableView;
        });

        addTest("ListView Demo", ()->{
            ListView<Activity> listView = new ListView();
            listCell(listView);
            return listView;
        });

        addTest("ProgressBar Demo", ()->{
            HBox hBox = new HBox(50);
            ProgressBar progessBar = new ProgressBar(0.4);
//            progessBar.getStyleClass().add("progress-bar-success");
            hBox.getChildren().addAll(progessBar, new Label("dasfasfas"));
            return hBox;
        });

        addTest("PieChart Demo", ()->{
            PieChart qualityPieChart = new PieChart();
            ObservableList<PieChart.Data> pieChartData =
                    FXCollections.observableArrayList(
                            new PieChart.Data("Grapefruit", 13),
                            new PieChart.Data("Oranges", 25),
                            new PieChart.Data("Apples", 30));
            qualityPieChart.setData(pieChartData);

            qualityPieChart.setLabelsVisible(false);

//        qualityPieChart.setLabelLineLength(10);
//            qualityPieChart.setLegendSide(Side.BOTTOM);

            qualityPieChart.setStyle("-fx-background-color: red; -fx-padding: 0px;");
            qualityPieChart.setMaxSize(550, 460);
            HBox hBox = new HBox();
            hBox.getChildren().addAll(qualityPieChart);
            return hBox;
        });

        addTest("BarChart Demo", ()->{
            final String austria = "澳大利亚";
            final String brazil = "Brazil";
            final String france = "法国";
            final String italy = "Italy";
            final String usa = "美国";

            final NumberAxis xAxis = new NumberAxis();
            final CategoryAxis yAxis = new CategoryAxis();
            final BarChart<Number,String> bc = new BarChart<>(xAxis,yAxis);
            bc.setTitle("Country Summary");
            xAxis.setLabel("Value");
            xAxis.setTickLabelRotation(90);
            yAxis.setLabel("Country");

            XYChart.Series series1 = new XYChart.Series();
            series1.setName("2003");
            series1.getData().add(new XYChart.Data(25601.34, austria));
            series1.getData().add(new XYChart.Data(20148.82, brazil));
            series1.getData().add(new XYChart.Data(10000, france));
            series1.getData().add(new XYChart.Data(35407.15, italy));
            series1.getData().add(new XYChart.Data(12000, usa));

            XYChart.Series series2 = new XYChart.Series();
            series2.setName("2004");
            series2.getData().add(new XYChart.Data(57401.85, austria));
            series2.getData().add(new XYChart.Data(41941.19, brazil));
            series2.getData().add(new XYChart.Data(45263.37, france));
            series2.getData().add(new XYChart.Data(117320.16, italy));
            series2.getData().add(new XYChart.Data(14845.27, usa));

            XYChart.Series series3 = new XYChart.Series();
            series3.setName("2005");
            series3.getData().add(new XYChart.Data(45000.65, austria));
            series3.getData().add(new XYChart.Data(44835.76, brazil));
            series3.getData().add(new XYChart.Data(18722.18, france));
            series3.getData().add(new XYChart.Data(17557.31, italy));
            series3.getData().add(new XYChart.Data(92633.68, usa));

            bc.getData().addAll(series1, series2, series3);
            return bc;
        });

        addTest("Gauge Demo2", ()->{
            FlowPane flowPane = new FlowPane();
            for(Gauge.SkinType skinType : Gauge.SkinType.values()) {
                Gauge gauge = GaugeBuilder.create()
                        .skinType(skinType)
                        .prefSize(200, 200)
                        .foregroundBaseColor(Color.web("#88ada6"))
                        .barBackgroundColor(Color.web("#6b98b4"))
                        .decimals(10)
                        .value(187)
                        .maxValue(200)
                        .title(skinType.name())
                        .subTitle(skinType.name())
                        .titleColor(Color.BLACK)
//                .arcExtend(5)
                        .gradientLookup(new GradientLookup(new Stop(0, Color.web("#8f62cb")),
                                new Stop(0.25, Color.web("#7367f0")),
                                new Stop(0.5, Color.web("#ad5ea5")),
                                new Stop(0.75, Color.web("#e85456")),
                                new Stop(1.0, Color.web("#e85456").brighter())))
                        .gradientBarEnabled(true)
                        .animated(true)
                        .build();
                flowPane.getChildren().add(gauge);
            }

            return flowPane;
        });

        addTest("LineChart 性能测试", ()->{
            NumberAxis xAxis = new NumberAxis(0, 50_000, 5000);
            xAxis.setAutoRanging(false);
            NumberAxis yAxis = new NumberAxis(-1, 1, 25);
            yAxis.setAutoRanging(false);
            LineChart<Number, Number> graph = new LineChart<>(xAxis, yAxis);
            graph.setAnimated(false);
            graph.setCreateSymbols(false);
            graph.setLegendVisible(false);
            XYChart.Series<Number, Number> series = new XYChart.Series<>();;

            Random math = new Random();
            long starttime = System.nanoTime();
            for(int n = 0; n < 5000; n++){
                series.getData().add(new XYChart.Data(n, math.nextDouble() * 25));
            }
            long endtime = System.nanoTime();
            System.out.println("添加数据的时间(毫秒)："+(endtime-starttime)/ 1e6);

            graph.getData().add(series);
            return graph;
        });

        addTest("TextFlow Demo", ()->{
            TextFlow textFlow = new TextFlow();
            textFlow.setPadding(new Insets(10));
            textFlow.setLineSpacing(10);
            TextField textField = new TextField();
            Button button = new Button("Send");
            button.setPrefWidth(70);

            VBox container = new VBox();
            container.getChildren().addAll(textFlow, new HBox(textField, button));
            VBox.setVgrow(textFlow, Priority.ALWAYS);

            // Textfield re-sizes according to VBox
            textField.prefWidthProperty().bind(container.widthProperty().subtract(button.prefWidthProperty()));

            // On Enter press
            textField.setOnKeyPressed(e -> {
                if(e.getCode() == KeyCode.ENTER) {
                    button.fire();
                }
            });

            button.setOnAction(e -> {
                Text text;
                if(textFlow.getChildren().size()==0){
                    text = new Text(textField.getText());
                } else {
                    // Add new line if not the first child
                    text = new Text("\n" + textField.getText());
                }
                if(textField.getText().contains(":)")) {
                    ImageView imageView = new ImageView("http://files.softicons.com/download/web-icons/network-and-security-icons-by-artistsvalley/png/16x16/Regular/Friend%20Smiley.png");
                    // Remove :) from text
                    text.setText(text.getText().replace(":)"," "));
                    textFlow.getChildren().addAll(text, imageView);
                } else {
                    textFlow.getChildren().add(text);
                    text.setText(text.getText().replace(":)"," "));
                    text.setSelectionStart(0);
                    text.setSelectionEnd(text.getText().length());
                }
                textField.clear();
                textField.requestFocus();

            });
            return container;
        });

        addTest("TextFlow Demo", ()->{
            TextFlow textFlow = new TextFlow();
            textFlow.setPadding(new Insets(10));
            textFlow.setLineSpacing(10);

            TextField textField = new TextField();
            HBox.setHgrow(textField, Priority.ALWAYS);
            Button button = new Button("add");
            button.setOnAction(e->{
                Text text = new Text(textField.getText());

                textFlow.getChildren().add(text);
                textField.setText("");
            });
            HBox hBox = new HBox(textField, button);
            VBox.setVgrow(textFlow, Priority.ALWAYS);
            VBox vBox = new VBox(textFlow, hBox);
            return vBox;
        });

        addTest("TextFlow width Demo", ()->{
            VBox vBox = new VBox();
            TextFlow textFlow = new TextFlow();
            TextField textField =new TextField();
            Text text = new Text();
            text.setSelectionFill(Color.RED);
            Button button = new Button("clear");
            button.setOnAction(e->{
                text.setText("");
            });
            Button button2 = new Button("add image");
            button2.setOnAction(e->{
                ImageView imageView = new ImageView(new Image(this.getClass().getResource("/img/48.jpg").toExternalForm()));
                imageView.setFitWidth(50);imageView.setFitHeight(50);
                textFlow.getChildren().add(imageView);
                Text text1 = new Text("asfdafas");
                textFlow.getChildren().add(text1);
            });
            double d = RegionUtil.calcStringWidth("a");
            text.setOnDragDetected(e->{
                double x = e.getX();
                x = text.localToParent(x, e.getY()).getX();
                int s = (int)(x/d)-1;
                System.out.println("x:" + s);
                text.setSelectionStart(s);
                text.setSelectionEnd(s);
                text.setCaretBias(true);
                text.setCaretPosition(s);
            });
            text.setOnMouseDragged(e->{
                double x = e.getX();
                x = text.localToParent(x, e.getY()).getX();
                int s = (int)(x/d);
                text.setSelectionEnd(s);
            });
            textField.textProperty().addListener((InvalidationListener)l->{
                String t = textField.getText();
                if (t.equals("")) return;
                text.setText(text.getText() + t);
                textField.setText("");
            });
            textFlow.getChildren().addAll(text, textField, button, button2);
            vBox.getChildren().add(textFlow);
            return vBox;
        });

        addTest("FlowPane Demo", ()->{
            FlowPane flowPane = new FlowPane(10, 10);
            for(int i=0; i<5000; i++) {
                Button b = new Button("用户" + i);
                flowPane.getChildren().add(b);
            }
            ScrollPane scrollPane = new ScrollPane(flowPane);
            scrollPane.setFitToWidth(true);
            return scrollPane;
        });
    }

    private Node buildTop() {
        HBox hBox = new HBox();
        hBox.getStyleClass().add("demo-header");
        Label title = new Label("javafx 测试平台");
        hBox.getChildren().add(title);
        return hBox;
    }

    private void addTest(String title, Supplier<Node> supplier) {
        JFXButton jfxButton = new JFXButton(title);
        leftPane.getChildren().add(jfxButton);
        jfxButton.setOnAction(e->{
            Node node = supplier.get();
            if (node == null) return;
            contentPane.getChildren().clear();
            contentPane.getChildren().add(node);
        });
    }

    private Function<Activity, Node> listCell(ListView<Activity> activityListView) {
        Function<Activity, Node> function = activity->{
            GridPane gridPane = new GridPane();
            gridPane.getStyleClass().add("list-node");
            FontIcon fontIcon1 = FontIcon.of(FontAwesome.findByDescription(activity.getIconDescription()), 20, Color.WHITE);
            Label iconLabel = new Label();
            iconLabel.getStyleClass().add("icon-label");
            iconLabel.setGraphic(fontIcon1);

            Label title = new Label(activity.getTitle());
            title.getStyleClass().add("title-label");
            Label subTitle = new Label(activity.getSubTitle());
            subTitle.getStyleClass().add("subtitle-label");
            gridPane.getChildren().addAll(iconLabel, title, subTitle);
            int row =0, col=0;
            GridPane.setConstraints(iconLabel, col++, row, 1, 2);
            GridPane.setConstraints(title, col, row++, 2, 1);
            GridPane.setConstraints(subTitle, col, row, 1, 1);
            return gridPane;
        };
        activityListView.setCellFactory(new ObjectListCell(function));

        activityListView.getItems().addAll(loadActivityList());
        return function;
    }

    private List<Activity> loadActivityList() {
        List<Activity> activities = new ArrayList();
        for(int i=0; i<10; i++) {
            Activity activity = new Activity();
            activity.setIconDescription(FontAwesome.SEARCH.getDescription());
            activity.setTitle("demo " + i);
            activity.setSubTitle("sub demo "+ i);
            activity.setLocalDateTime(LocalDateTime.now());

            activities.add(activity);
        }
        return activities;
    }

    private BarChart<Number, String> loadMouldBarChartData() {
        BarChart<Number, String> mouldBarChart = new BarChart<>(new NumberAxis(), new CategoryAxis());


        System.out.println(mouldBarChart.getYAxis().getSide().toString());
        XYChart.Series<Number, String> series1 = new XYChart.Series();
        series1.setName("2003");
        series1.getData().add(new XYChart.Data(10.0, "设变"));
        series1.getData().add(new XYChart.Data(29.0, "修模"));
        series1.getData().add(new XYChart.Data(49.0, "新模"));

        XYChart.Series<Number, String> series2 = new XYChart.Series();
        series2.setName("2004");
        series2.getData().add(new XYChart.Data(30.5, "设变"));
        series2.getData().add(new XYChart.Data(20.5, "修模"));
        series2.getData().add(new XYChart.Data(40.3, "新模"));

        mouldBarChart.getData().addAll(series1, series2);
        return mouldBarChart;
    }
}
